<template>
  <view
    v-if="inited"
    :class="[
      'fu-transition',
      customClass,
      `fu-${name}`,
      {
        'fu-transition--show': show
      }
    ]"
    :style="mergeStyle"
    @transitionend="onTransitionEnd"
    @animationend="onAnimationEnd"
  >
    <slot></slot>
  </view>
</template>

<script>
/**
 * fu-transition 动画组件
 * @description 用于提供多种过渡动画效果
 * @property {String} name - 动画类型，可选值：fade/fade-up/fade-down/fade-left/fade-right/slide-up/slide-down/slide-left/slide-right/zoom
 * @property {Boolean} show - 是否显示组件
 * @property {String} customClass - 自定义类名
 * @property {Number} duration - 动画时长，单位ms
 * @property {Object} customStyle - 自定义样式
 * @event {Function} beforeEnter - 进入前触发
 * @event {Function} enter - 进入时触发
 * @event {Function} afterEnter - 进入后触发
 * @event {Function} beforeLeave - 离开前触发
 * @event {Function} leave - 离开时触发
 * @event {Function} afterLeave - 离开后触发
 */
export default {
  name: 'fu-transition',
  props: {
    // 动画类型
    name: {
      type: String,
      default: 'fade'
    },
    // 是否展示组件
    show: {
      type: Boolean,
      default: false
    },
    // 自定义类名
    customClass: {
      type: String,
      default: ''
    },
    // 动画时长，单位ms
    duration: {
      type: Number,
      default: 300
    },
    // 自定义样式
    customStyle: {
      type: Object,
      default: () => ({})
    }
  },
  data() {
    return {
      inited: false,
      display: false,
      status: ''
    }
  },
  computed: {
    mergeStyle() {
      const style = {
        transitionDuration: `${this.duration}ms`,
        ...this.customStyle
      }
      return style
    }
  },
  watch: {
    show: {
      handler(newVal) {
        if (newVal) {
          this.observeShow()
        } else {
          this.observeHide()
        }
      },
      immediate: true
    }
  },
  methods: {
    observeShow() {
      const { show } = this
      if (show) {
        this.status = 'enter'
        this.$emit('beforeEnter')
        this.inited = true
        this.$nextTick(() => {
          this.$emit('enter')
          setTimeout(() => {
            this.$emit('afterEnter')
          }, this.duration)
        })
      }
    },
    observeHide() {
      const { show } = this
      if (!show) {
        this.status = 'leave'
        this.$emit('beforeLeave')
        this.$nextTick(() => {
          this.$emit('leave')
          setTimeout(() => {
            this.inited = false
            this.$emit('afterLeave')
          }, this.duration)
        })
      }
    },
    onTransitionEnd() {
      if (this.status === 'leave') {
        this.inited = false
      }
    },
    onAnimationEnd() {
      if (this.status === 'leave') {
        this.inited = false
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.fu-transition {
  transition-timing-function: ease;
  
  // fade淡入淡出
  &.fu-fade {
    opacity: 0;
    &.fu-transition--show {
      opacity: 1;
    }
  }
  
  // fade-up 从下淡入
  &.fu-fade-up {
    transform: translate3d(0, 100%, 0);
    opacity: 0;
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
  }
  
  // fade-down 从上淡入
  &.fu-fade-down {
    transform: translate3d(0, -100%, 0);
    opacity: 0;
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
  }
  
  // fade-left 从左淡入
  &.fu-fade-left {
    transform: translate3d(-100%, 0, 0);
    opacity: 0;
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
  }
  
  // fade-right 从右淡入
  &.fu-fade-right {
    transform: translate3d(100%, 0, 0);
    opacity: 0;
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
  }
  
  // slide-up 上滑进入
  &.fu-slide-up {
    transform: translate3d(0, 100%, 0);
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
    }
  }
  
  // slide-down 下滑进入
  &.fu-slide-down {
    transform: translate3d(0, -100%, 0);
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
    }
  }
  
  // slide-left 左滑进入
  &.fu-slide-left {
    transform: translate3d(-100%, 0, 0);
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
    }
  }
  
  // slide-right 右滑进入
  &.fu-slide-right {
    transform: translate3d(100%, 0, 0);
    &.fu-transition--show {
      transform: translate3d(0, 0, 0);
    }
  }
  
  // zoom 缩放
  &.fu-zoom {
    transform: scale(0.8);
    opacity: 0;
    &.fu-transition--show {
      transform: scale(1);
      opacity: 1;
    }
  }
}
</style> 